package my.edu.ai.service;

import cn.hutool.crypto.digest.MD5;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonParser;
import my.edu.ai.entity.AiChat;
import my.edu.ai.entity.vo.AiChatVO;
import my.edu.ai.mapper.AiChatMapper;
import my.edu.common.exception.BillsException;
import my.edu.security.userEntity.UserDetail;
import org.apache.shiro.SecurityUtils;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.messages.AssistantMessage;
import org.springframework.ai.chat.messages.Message;
import org.springframework.ai.chat.messages.UserMessage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Random;

@Service
public class IAiChatServiceImpl extends ServiceImpl<AiChatMapper, AiChat> implements IAiChatService {

    @Autowired
    private ChatClient chatClient;

    @Override
    public List<Message> getMessagesByConversationId(String conversationId, int lastN) {
        AiChat aiChat = lambdaQuery().eq(AiChat::getConversationId, conversationId).one();
        JSONArray chatArray = JSONUtil.parseArray(aiChat.getChatContent());
        List<Object> msgList = JSONUtil.toList(chatArray, Object.class);
        int size = msgList.size();
        List<Message> res = new ArrayList<>();

        for (int i = 0; i < size; i++) {
            JSONObject jsonObject = (JSONObject) msgList.get(i);
            if (jsonObject.containsKey("messageType") && "USER".equals(jsonObject.getStr("messageType"))) {
//                UserMessage userMessage = BeanUtil.toBean(jsonObject, UserMessage.class);
                res.add(new UserMessage(jsonObject.getStr("textContent")));
            } else {
                Map<String, Object> metadata = jsonObject.getJSONObject("metadata").getRaw();
//                AssistantMessage assistantMessage = BeanUtil.toBean(jsonObject, AssistantMessage.class);
                res.add(new AssistantMessage(jsonObject.getStr("textContent"), metadata));
            }
        }
        return res;
    }


    @Override
    public void addMessages(String conversationId, List<Message> messages) throws JsonProcessingException {
        AiChat aiChat = lambdaQuery().eq(AiChat::getConversationId, conversationId).one();
        Gson gson = new Gson();

        // 解析 chatContent
        String chatContent = aiChat.getChatContent();
        JsonArray chatArray;

        if (chatContent == null || chatContent.isEmpty()) {
            chatArray = new JsonArray();
        } else {
            chatArray = JsonParser.parseString(chatContent).getAsJsonArray();
        }

        JsonElement msgJson = gson.toJsonTree(messages.get(0));
        chatArray.add(msgJson);


        // 超过 10 条时删除最早的消息
        while (chatArray.size() > 20) {
            chatArray.remove(0);
        }

        // 序列化 JSON
        String json = gson.toJson(chatArray);

        // 更新数据库
        if (chatArray.size() == 1) {
            String textContent = msgJson.getAsJsonObject().get("textContent").getAsString();
            textContent = textContent.length() > 7 ? textContent.substring(0, 7) + "..." : textContent;
            lambdaUpdate()
                    .set(AiChat::getChatContent, json)
                    .set(AiChat::getChatName, textContent)
                    .eq(AiChat::getConversationId, conversationId)
                    .update();
        } else {
            lambdaUpdate()
                    .set(AiChat::getChatContent, json)
                    .eq(AiChat::getConversationId, conversationId)
                    .update();
        }
    }

    @Override
    public JSONObject addChat() {
        UserDetail principal = (UserDetail) SecurityUtils.getSubject().getPrincipal();
        Long userId = principal.getId();
        Long count = lambdaQuery().eq(AiChat::getUserId, userId).count();
        if (count >= 20) {
            throw new BillsException("最多能创建20个会话");
        }

        Random random = new Random();
        // 生成一个随机整数
        int randomInt = random.nextInt(10000);
        Integer chatId = Integer.valueOf(userId + "" + randomInt);
        AiChat build = AiChat.builder()
                .conversationId(MD5.create().digestHex(userId + chatId + ""))
                .userId(userId)
                .chatId(chatId)
                .chatName("新对话")
                .chatContent("[]")
                .build();
        save(build);
        return new JSONObject()
                .putOnce("chatName", build.getChatName())
                .putOnce("chatId", chatId);
    }

    @Override
    public String getConversationId(Integer chatId) {
        UserDetail principal = (UserDetail) SecurityUtils.getSubject().getPrincipal();
        Long userId = principal.getId();
        AiChat one = lambdaQuery()
                .eq(AiChat::getChatId, chatId)
                .eq(AiChat::getUserId, userId)
                .one();
        return one.getConversationId();
    }

    @Override
    public void removeByChatId(Integer chatId) {
        UserDetail principal = (UserDetail) SecurityUtils.getSubject().getPrincipal();
        Long userId = principal.getId();
        lambdaUpdate().eq(AiChat::getChatId, chatId).eq(AiChat::getUserId, userId).remove();
    }

    @Override
    public List<AiChatVO> listChat() {
        UserDetail principal = (UserDetail) SecurityUtils.getSubject().getPrincipal();
        Long userId = principal.getId();
//        List<AiChat> list = lambdaQuery()
//                .eq(AiChat::getUserId, userId).list();
        MPJLambdaWrapper<AiChat> w = new MPJLambdaWrapper<AiChat>()
                .selectAsClass(AiChat.class, AiChatVO.class)
                .eq(AiChat::getUserId, userId);
        return baseMapper.selectJoinList(AiChatVO.class, w);
    }

    @Override
    public AiChat getOneChat(Integer chatId) {
        UserDetail principal = (UserDetail) SecurityUtils.getSubject().getPrincipal();
        Long userId = principal.getId();
        return lambdaQuery().eq(AiChat::getUserId, userId).eq(AiChat::getChatId, chatId).one();
    }
}
